home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 November: Tool Chest / Dev.CD Nov 98 TC.toast / Sample Code / Networking / OT PAPServerSample / StringUtils.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-08-28  |  15.4 KB  |  783 lines  |  [TEXT/CWIE]

  1. /*
  2. **    Apple Macintosh Developer Technical Support
  3. **
  4. **    Collection of String Utilities for DTS Sample code
  5. **
  6. **    File:        StringUtils.c
  7. **
  8. **    Copyright © 1988-1993 Apple Computer, Inc.
  9. **    All rights reserved.
  10. */
  11.  
  12. /* You may incorporate this sample code into your applications without
  13. ** restriction, though the sample code has been provided "AS IS" and the
  14. ** responsibility for its operation is 100% yours.  However, what you are
  15. ** not permitted to do is to redistribute the source as "DSC Sample Code"
  16. ** after having made changes. If you're going to re-distribute the source,
  17. ** we require that you make it clear in the source that the code was
  18. ** descended from Apple Sample Code, but that you've made changes. */
  19.  
  20. #ifndef __MEMORY__
  21. #include <Memory.h>
  22. #endif
  23.  
  24. #ifndef __STRINGUTILS__
  25. #include "StringUtils.h"
  26. #endif
  27.  
  28. #ifndef __COMPENV__
  29. #include "CompEnv.h"
  30. #endif
  31.  
  32.  
  33.  
  34. /* These functions should be linked into whatever segment holds main().  This will
  35. ** guarantee that the functions will always be in memory when called.  It is important
  36. ** that they are in memory, because if a pointer is passed in that points into an
  37. ** unlocked handle, the mere fact that the code needs to get loaded may cause the
  38. ** handle that is pointed into to move.  If you stick to these string functions,
  39. ** you will not have to worry about the handle moving when the string function is
  40. ** called.  If you have your own string functions, and you wish the same safety
  41. ** factor, link the string handling code into the same segment as main(), as you
  42. ** do with these string functions. */
  43.  
  44. static short    gBase;
  45. static Boolean    gHandleChars;
  46.  
  47.  
  48.  
  49. /*****************************************************************************/
  50. /*****************************************************************************/
  51.  
  52. #ifdef applec
  53. #pragma segment ATGStringUtils
  54. #endif
  55.  
  56. /*****************************************************************************/
  57. /*****************************************************************************/
  58.  
  59.  
  60.  
  61. /* Return the length of the c-string.  (Same as strlen, but this function isn't
  62. ** part of the string library.  The entire library may be more than you wish to
  63. ** link into the code segment that holds main, so this (and other) standard
  64. ** library function has been duplicated here. */
  65.  
  66. short    clen(char *cptr)
  67. {
  68.     short    i;
  69.  
  70.     for (i = 0; cptr[i]; ++i) {};
  71.     return(i);
  72. }
  73.  
  74.  
  75.  
  76. /*****************************************************************************/
  77.  
  78.  
  79.  
  80. /* Catenate two c-strings. */
  81.  
  82. char    *ccat(char *s1, char *s2)
  83. {
  84.     ccpy(s1 + clen(s1), s2);
  85.     return(s1);
  86. }
  87.  
  88.  
  89.  
  90. /*****************************************************************************/
  91.  
  92.  
  93.  
  94. /* Copy a c-string. */
  95.  
  96. char    *ccpy(char *s1, char *s2)
  97. {
  98.     char    *c1, *c2;
  99.  
  100.     c1 = s1;
  101.     c2 = s2;
  102.     while ((*c1++ = *c2++) != 0) {};
  103.     return(s1);
  104. }
  105.  
  106.  
  107.  
  108. /*****************************************************************************/
  109.  
  110.  
  111.  
  112. /* Compare two pascal-strings. */
  113.  
  114. short    pcmp(StringPtr s1, StringPtr s2)
  115. {
  116.     short    i, len, j;
  117.  
  118.     if ((len = s1[0]) > s2[0]) len = s2[0];
  119.  
  120.     for (i = 1; i <= len; ++i) {
  121.         j = ((unsigned short)s1[i] - (unsigned short)s2[i]);
  122.         if (j) return(j);
  123.     }
  124.  
  125.     return(s1[0] - s2[0]);
  126. }
  127.  
  128.  
  129.  
  130. /*****************************************************************************/
  131.  
  132.  
  133.  
  134. /* Catenate two pascal-strings. */
  135.  
  136. void    pcat(StringPtr d, StringPtr s)
  137. {
  138.     short    i, j;
  139.  
  140.     if (((j = s[0]) + d[0]) > 255)
  141.         j = 255 - d[0];
  142.             /* Limit dest string to 255. */
  143.  
  144.     for (i = 0; i < j;) d[++d[0]] = s[++i];
  145. }
  146.  
  147.  
  148.  
  149. /*****************************************************************************/
  150.  
  151.  
  152.  
  153. /* Copy a pascal-string. */
  154.  
  155. void    pcpy(StringPtr d, StringPtr s)
  156. {
  157.     short    i;
  158.  
  159.     i = *s;
  160.     do {
  161.         d[i] = s[i];
  162.     } while (i--);
  163. }
  164.  
  165.  
  166.  
  167. /*****************************************************************************/
  168.  
  169.  
  170.  
  171. /* Convert a c-string to a pascal-string. */
  172.  
  173. void    c2p(char *cptr)
  174. {
  175.     short    len;
  176.  
  177.     BlockMove(cptr, cptr + 1, len = clen(cptr));
  178.     *cptr = len;
  179. }
  180.  
  181.  
  182.  
  183. /*****************************************************************************/
  184.  
  185.  
  186.  
  187. /* Convert a pascal-string to a c-string. */
  188.  
  189. void    p2c(StringPtr cptr)
  190. {
  191.     unsigned char    len;
  192.  
  193.     BlockMove(cptr + 1, cptr, len = *cptr);
  194.     cptr[len] = 0;
  195. }
  196.  
  197.  
  198.  
  199. /*****************************************************************************/
  200. /*****************************************************************************/
  201. /*****************************************************************************/
  202.  
  203.  
  204.  
  205. /* Catenate a single character multiple times onto the designated string. */
  206.  
  207. void    ccatchr(char *cptr, char c, short count)
  208. {
  209.     ccpychr(cptr + clen(cptr), c, count);
  210. }
  211.  
  212.  
  213.  
  214. /*****************************************************************************/
  215.  
  216.  
  217.  
  218. /* Convert the value into text for the base-10 number and catenate it to
  219. ** the designated string.  The value is assumed to be signed.  If you wish
  220. ** to have an unsigned decimal value, call ccatnum with a base of 10. */
  221.  
  222. void    ccatpaddec(char *cptr, char padChr, short minApnd, short maxApnd, long v)
  223. {
  224.     ccatpadnum(cptr + clen(cptr), padChr, minApnd, maxApnd, v, -10);
  225.         /* Catenate value base 10, signed. */
  226. }
  227.  
  228. void    ccatdec(char *cptr, long v)
  229. {
  230.     ccatnum(cptr, v, -10);
  231. }
  232.  
  233.  
  234.  
  235. /*****************************************************************************/
  236.  
  237.  
  238.  
  239. /* Convert the value into text for base-16, format it, and catenate it to the
  240. ** designated string.  ccatnum could be used, since it handles multiple bases,
  241. ** but ccathex allows for additional common formatting and padding of the
  242. ** hex value. */
  243.  
  244. void    ccatpadhex(char *cptr, char padChr, short minApnd, short maxApnd, long v)
  245. {
  246.     char    str[33], *sptr;
  247.     short    len;
  248.  
  249.     cptr += clen(cptr);            /* We're appending, so point to the end of the string. */
  250.     ccpynum(str, v, 16);        /* Generate minimum-digit hex value. */
  251.  
  252.     if ((len = clen(sptr = str)) > maxApnd)
  253.         sptr = str + len - maxApnd;
  254.  
  255.     if ((len = clen(sptr)) < minApnd)
  256.         if (padChr)
  257.             ccatchr(cptr, padChr, (minApnd - len));
  258.                 /* if we have a pad character, and if necessary, pad the string. */
  259.  
  260.     ccat(cptr, sptr);            /* Add the hex digits to the string. */
  261. }
  262.  
  263. void    ccathex(char *cptr, long v)
  264. {
  265.     ccatpadhex(cptr, 0, 0, 8, v);
  266. }
  267.  
  268.  
  269.  
  270. /*****************************************************************************/
  271.  
  272.  
  273.  
  274. /* Convert the value into text for the designated base.  Catenate the text to
  275. ** the designated string. */
  276.  
  277. void    ccatpadnum(char *cptr, char padChr, short minApnd, short maxApnd, long v, short base)
  278. {
  279.     ccpypadnum(cptr + clen(cptr), padChr, minApnd, maxApnd, v, base);
  280. }
  281.  
  282. void    ccatnum(char *cptr, long v, short base)
  283. {
  284.     ccpynum(cptr + clen(cptr), v, base);
  285. }
  286.  
  287.  
  288.  
  289. /*****************************************************************************/
  290.  
  291.  
  292.  
  293. void    ccpychr(char *cptr, char c, short count)
  294. {
  295.     for (;count--; ++cptr) *cptr = c;
  296.     *cptr = 0;
  297. }
  298.  
  299.  
  300.  
  301. /*****************************************************************************/
  302.  
  303.  
  304.  
  305. void    ccpypaddec(char *cptr, char padChr, short minApnd, short maxApnd, long v)
  306. {
  307.     ccpypadnum(cptr, padChr, minApnd, maxApnd, v, -10);
  308. }
  309.  
  310. void    ccpydec(char *cptr, long v)
  311. {
  312.     ccpynum(cptr, v, -10);
  313. }
  314.  
  315.  
  316.  
  317. /*****************************************************************************/
  318.  
  319.  
  320.  
  321. void    ccpypadhex(char *cptr, char padChr, short minApnd, short maxApnd, long v)
  322. {
  323.     cptr[0] = 0;
  324.     ccatpadhex(cptr, padChr, minApnd, maxApnd, v);
  325. }
  326.  
  327. void    ccpyhex(char *cptr, long v)
  328. {
  329.     cptr[0] = 0;
  330.     ccathex(cptr, v);
  331. }
  332.  
  333.  
  334.  
  335. /*****************************************************************************/
  336.  
  337.  
  338.  
  339. void    ccpypadnum(char *cptr, char padChr, short minApnd, short maxApnd, long v, short base)
  340. {
  341.     pcpypadnum((StringPtr)cptr, padChr, minApnd, maxApnd, v, base);
  342.     p2c((StringPtr)cptr);
  343. }
  344.  
  345. void    ccpynum(char *cptr, long v, short base)
  346. {
  347.     pcpynum((StringPtr)cptr, v, base);
  348.     p2c((StringPtr)cptr);
  349. }
  350.  
  351.  
  352.  
  353. /*****************************************************************************/
  354. /*****************************************************************************/
  355. /*****************************************************************************/
  356.  
  357.  
  358.  
  359. long    c2dec(char *cptr, short *charsUsed)
  360. {
  361.     return(c2num(cptr, 10, charsUsed));
  362. }
  363.  
  364.  
  365.  
  366. /*****************************************************************************/
  367.  
  368.  
  369.  
  370. long    c2hex(char *cptr, short *charsUsed)
  371. {
  372.     return(c2num(cptr, 16, charsUsed));
  373. }
  374.  
  375.  
  376.  
  377. /*****************************************************************************/
  378.  
  379.  
  380.  
  381. long    c2num(char *cptr, short base, short *charsUsed)
  382. {
  383.     Boolean    firstDigit;
  384.     short    i, sgn;
  385.     short    c;
  386.     long    val;
  387.  
  388.     sgn = 1;
  389.     for (firstDigit = false, val = 0, i = 0;;) {
  390.         c = cptr[i++];
  391.         if (base == 256) {
  392.             if (!c) break;
  393.             if (c == '\'') {
  394.                 ++i;
  395.                 break;
  396.             }
  397.             val *= base;
  398.             val += c;
  399.             continue;
  400.         }
  401.         if (c == '-') {
  402.             if (firstDigit) break;
  403.             if (sgn == -1)  break;
  404.             sgn = -1;
  405.             continue;
  406.         }
  407.         if (c == '$') {
  408.             if (firstDigit) break;
  409.             base = 16;
  410.             continue;
  411.         }
  412.         if (gHandleChars) {
  413.             if (c == '\'') {
  414.                 if (firstDigit) break;
  415.                 base = 256;
  416.                 continue;
  417.             }
  418.         }
  419.         if (base == 10) {
  420.             if (c < '0') break;
  421.             if (c > '9') break;
  422.         }
  423.         if ((!firstDigit) && (c == ' ')) continue;
  424.         c -= '0';
  425.         if (base == 16) {
  426.             if (c > 16) c -= 7;        /* Make 'A' a 10, etc. */
  427.             if (c > 32) c -= 32;    /* Make lower-case upper-case. */
  428.         }
  429.         if (c < 0) break;
  430.         if (c >= base) break;
  431.         val *= base;
  432.         val += (c * sgn);
  433.         firstDigit = true;
  434.     }
  435.  
  436.     if (charsUsed) *charsUsed = --i;
  437.  
  438.     gBase = base;
  439.     return(val);
  440. }
  441.  
  442.  
  443.  
  444. /*****************************************************************************/
  445.  
  446.  
  447.  
  448. short    GetLastBase(Boolean handleChars)
  449. {
  450.     gHandleChars = handleChars;
  451.     return(gBase);
  452. }
  453.  
  454.  
  455.  
  456. /*****************************************************************************/
  457. /*****************************************************************************/
  458. /*****************************************************************************/
  459.  
  460.  
  461.  
  462. /* Catenate a single character multiple times onto the designated string. */
  463.  
  464. void    pcatchr(StringPtr pptr, char c, short count)
  465. {
  466.     while (count--) pptr[++(pptr[0])] = c;
  467. }
  468.  
  469.  
  470.  
  471. /*****************************************************************************/
  472.  
  473.  
  474.  
  475. void    pcatpaddec(StringPtr pptr, char padChr, short minApnd, short maxApnd, long v)
  476. {
  477.     pcatpadnum(pptr, padChr, minApnd, maxApnd, v, -10);
  478. }
  479.  
  480. void    pcatdec(StringPtr pptr, long v)
  481. {
  482.     pcatnum(pptr, v, -10);
  483. }
  484.  
  485.  
  486.  
  487. /*****************************************************************************/
  488.  
  489.  
  490.  
  491. void    pcatpadhex(StringPtr pptr, char padChr, short minApnd, short maxApnd, long v)
  492. {
  493.     char    str[33];
  494.  
  495.     ccpypadhex(str, padChr, minApnd, maxApnd, v);
  496.     c2p(str);
  497.     pcat(pptr, (StringPtr)str);
  498. }
  499.  
  500. void    pcathex(StringPtr pptr, long v)
  501. {
  502.     pcatpadhex(pptr, 0, 0, 8, v);
  503. }
  504.  
  505.  
  506.  
  507. /*****************************************************************************/
  508.  
  509.  
  510.  
  511. long    pcatnum(StringPtr pptr, long v, short base)
  512. {
  513.     unsigned long    j, vv;
  514.  
  515.     vv = v;
  516.     if (base < 0) {
  517.         base = -base;
  518.         if (v < 0) {
  519.             pptr[++*pptr] = '-';
  520.             vv = -vv;
  521.         }
  522.     }
  523.     j = 0;
  524.     if (vv >= base)
  525.         j = pcatnum(pptr, vv / base, base);
  526.  
  527.     pptr[++*pptr] = "0123456789ABCDEF"[vv - j];
  528.     return(base * vv);
  529. }
  530.  
  531. void    pcatpadnum(StringPtr pptr, char padChr, short minApnd, short maxApnd, long v, short base)
  532. {
  533.     Str32    str;
  534.  
  535.     pcpynum(str, v, base);        /* Generate minimum-digit hex value. */
  536.  
  537.     if (str[0] > maxApnd) str[0] = maxApnd;
  538.  
  539.     if (str[0] < minApnd)
  540.         if (padChr)
  541.             pcatchr(pptr, padChr, (minApnd - str[0]));
  542.                 /* if we have a pad character, and if necessary, pad the string. */
  543.  
  544.     pcat(pptr, str);            /* Add the hex digits to the string. */
  545. }
  546.  
  547.  
  548.  
  549. /*****************************************************************************/
  550.  
  551.  
  552.  
  553. void    pcpychr(StringPtr pptr, char c, short count)
  554. {
  555.     pptr[0] = 0;
  556.     pcatchr(pptr, c, count);
  557. }
  558.  
  559.  
  560.  
  561. /*****************************************************************************/
  562.  
  563.  
  564.  
  565. void    pcpypaddec(StringPtr pptr, char padChr, short minApnd, short maxApnd, long v)
  566. {
  567.     *pptr = 0;
  568.     pcatpaddec(pptr, padChr, minApnd, maxApnd, v);
  569. }
  570.  
  571. void    pcpydec(StringPtr pptr, long v)
  572. {
  573.     *pptr = 0;
  574.     pcatdec(pptr, v);
  575. }
  576.  
  577.  
  578.  
  579. /*****************************************************************************/
  580.  
  581.  
  582.  
  583. void    pcpypadnum(StringPtr pptr, char padChr, short minApnd, short maxApnd, long v, short base)
  584. {
  585.     *pptr = 0;
  586.     pcatpadnum(pptr, padChr, minApnd, maxApnd, v, base);
  587. }
  588.  
  589. void    pcpynum(StringPtr pptr, long v, short base)
  590. {
  591.     *pptr = 0;
  592.     pcatnum(pptr, v, base);
  593. }
  594.  
  595.  
  596.  
  597. /*****************************************************************************/
  598.  
  599.  
  600.  
  601. void    pcpypadhex(StringPtr pptr, char padChr, short minApnd, short maxApnd, long v)
  602. {
  603.     *pptr = 0;
  604.     pcatpadhex(pptr, padChr, minApnd, maxApnd, v);
  605. }
  606.  
  607. void    pcpyhex(StringPtr pptr, long v)
  608. {
  609.     pcpypadhex(pptr, 0, 0, 8, v);
  610. }
  611.  
  612.  
  613.  
  614. /*****************************************************************************/
  615.  
  616.  
  617.  
  618. long    p2dec(StringPtr pptr, short *charsUsed)
  619. {
  620.     return(p2num(pptr, 10, charsUsed));
  621. }
  622.  
  623.  
  624.  
  625. /*****************************************************************************/
  626.  
  627.  
  628.  
  629. long    p2hex(StringPtr pptr, short *charsUsed)
  630. {
  631.     return(p2num(pptr, 16, charsUsed));
  632. }
  633.  
  634.  
  635.  
  636. /*****************************************************************************/
  637.  
  638.  
  639.  
  640. long    p2num(StringPtr pptr, short base, short *charsUsed)
  641. {
  642.     long    val;
  643.  
  644.     p2c(pptr);
  645.     val = c2num((char *)pptr, base, charsUsed);
  646.     c2p((char *)pptr);
  647.     return(val);
  648. }
  649.  
  650.  
  651.  
  652. /*****************************************************************************/
  653. /*****************************************************************************/
  654. /*****************************************************************************/
  655.  
  656.  
  657.  
  658. short    GetHexByte(char *cptr)
  659. {
  660.     short    val, i, chr;
  661.  
  662.     for (val = 0, i = 0; i < 2; ++i) {
  663.         chr = cptr[i];
  664.         if (chr == '=') return(cptr[++i]);
  665.         if (chr == '≈') {
  666.             chr = cptr[++i];
  667.             if ((chr >= 'a') && (chr <= 'z')) chr -= 32;
  668.             return(chr);
  669.         }
  670.         if (chr > 'F')
  671.             chr -= 0x20;
  672.         if (chr > '9')
  673.             chr -= ('A' - '9' - 1);
  674.         val = (val << 4) + chr - '0';
  675.     }
  676.     return(val);
  677. }
  678.  
  679.  
  680.  
  681. /*****************************************************************************/
  682.  
  683.  
  684.  
  685. Boolean    EqualHandle(void *h1, void *h2)
  686. {
  687.     long    s1, s2;
  688.     Ptr        p1, p2;
  689.  
  690.     if ((h1) && (!h2)) return(false);
  691.     if ((h2) && (!h1)) return(false);
  692.     if ((s1 = GetHandleSize(h1)) != (s2 = GetHandleSize(h2))) return(false);
  693.  
  694.     p1 = *(Handle)h1;
  695.     p2 = *(Handle)h2;
  696.     for (s1 = 0; s1 < s2; ++s1)
  697.         if (p1[s1] != p2[s1]) return(false);
  698.         
  699.     return(true);
  700. }
  701.  
  702.  
  703.  
  704. /*****************************************************************************/
  705.  
  706.  
  707.  
  708. Boolean    EqualData(void *v1, void *v2, long size)
  709. {
  710.     Ptr        p1, p2;
  711.     long    ii;
  712.  
  713.     if ((v1) && (!v2)) return(false);
  714.     if ((v2) && (!v1)) return(false);
  715.  
  716.     p1 = (Ptr)v1;
  717.     p2 = (Ptr)v2;
  718.     for (ii = 0; ii < size; ++ii)
  719.         if (p1[ii] != p2[ii]) return(false);
  720.         
  721.     return(true);
  722. }
  723.  
  724.  
  725.  
  726. /*****************************************************************************/
  727.  
  728.  
  729.  
  730. void    SetMem(void *vptr, unsigned char c, unsigned long len)
  731. {
  732.     Ptr    ptr;
  733.  
  734.     ptr = (Ptr)vptr;
  735.     while (len--) *ptr++ = c;
  736. }
  737.  
  738.  
  739.  
  740. /*****************************************************************************/
  741.  
  742.  
  743.  
  744. OSErr    HInsert(Handle hh, long offset, void *dataptr, long delta);
  745. OSErr    HInsert(Handle hh, long offset, void *dataptr, long delta)
  746. {
  747.     long    dataSize;
  748.     char    *cptr;
  749.     OSErr    err;
  750.  
  751.     dataSize = GetHandleSize(hh);
  752.  
  753.     if (!(delta & 0x80000000L)) {
  754.         SetHandleSize(hh, dataSize + delta);
  755.         err = MemError();
  756.         if (err) return(err);
  757.     }
  758.     else {
  759.         offset -= delta;
  760.             /* We are removing what we are pointing/offset at, so the block that is to be moved is
  761.             ** after the data being removed at the offset.  The size of the data being removed is
  762.             ** i-delta, so therefore subtract this negative number from offset to skip past data. */
  763.     }
  764.  
  765.     cptr = (*(char **)hh) + offset;
  766.     BlockMove(cptr, cptr + delta, dataSize - offset);
  767.  
  768.     if (delta & 0x80000000L) {
  769.         SetHandleSize(hh, dataSize + delta);
  770.             /* Delta is negative -- we are deleting data.  dataptr is unused. */
  771.     }
  772.     else {
  773.         cptr = (*(char **)hh) + offset;
  774.         BlockMove(dataptr, cptr, delta);
  775.             /* Delta is positive -- we are adding data pointed at by dataptr. */
  776.     }
  777.  
  778.     return(noErr);
  779. }
  780.  
  781.  
  782.  
  783.